View Javadoc
1   package org.apache.maven.surefire.testng.conf;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.Method;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.maven.surefire.booter.ProviderParameterNames;
30  import org.apache.maven.surefire.testset.TestSetFailedException;
31  import org.testng.TestNG;
32  import org.testng.xml.XmlSuite;
33  
34  /**
35   * Configurator that relies on reflection to set parameters in TestNG
36   *
37   */
38  public abstract class AbstractDirectConfigurator
39      implements Configurator
40  {
41      final Map setters;
42  
43      AbstractDirectConfigurator()
44      {
45          Map options = new HashMap();
46          // options.put( ProviderParameterNames.TESTNG_GROUPS_PROP, new Setter( "setGroups", String.class ) );
47          // options.put( ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP, new Setter( "setExcludedGroups", String.class
48          // ) );
49          options.put( "junit", new Setter( "setJUnit", Boolean.class ) );
50          options.put( ProviderParameterNames.THREADCOUNT_PROP, new Setter( "setThreadCount", int.class ) );
51          options.put( "usedefaultlisteners", new Setter( "setUseDefaultListeners", boolean.class ) );
52          this.setters = options;
53      }
54  
55      public void configure( TestNG testng, Map options )
56          throws TestSetFailedException
57      {
58          System.out.println( "\n\n\n\nCONFIGURING TESTNG\n\n\n\n" );
59          // kind of ugly, but listeners are configured differently
60          final String listeners = (String) options.remove( "listener" );
61          // DGF In 4.7, default listeners dump XML files in the surefire-reports directory,
62          // confusing the report plugin.  This was fixed in later versions.
63          testng.setUseDefaultListeners( false );
64          configureInstance( testng, options );
65          // TODO: we should have the Profile so that we can decide if this is needed or not
66          testng.setListenerClasses( loadListenerClasses( listeners ) );
67      }
68  
69      public void configure( XmlSuite suite, Map options )
70          throws TestSetFailedException
71      {
72          Map filtered = filterForSuite( options );
73          configureInstance( suite, filtered );
74      }
75  
76  
77      protected Map filterForSuite( Map options )
78      {
79          Map result = new HashMap();
80          addPropIfNotNull( options, result, ProviderParameterNames.PARALLEL_PROP );
81          addPropIfNotNull( options, result, ProviderParameterNames.THREADCOUNT_PROP );
82          return result;
83      }
84  
85      private void addPropIfNotNull( Map options, Map result, String prop )
86      {
87          if ( options.containsKey( prop ) )
88          {
89              result.put( prop, options.get( prop ) );
90          }
91      }
92  
93      private void configureInstance( Object testngInstance, Map options )
94      {
95          for ( Iterator it = options.entrySet().iterator(); it.hasNext(); )
96          {
97              Map.Entry entry = (Map.Entry) it.next();
98              String key = (String) entry.getKey();
99              Object val = entry.getValue();
100 
101             Setter setter = (Setter) setters.get( key );
102             if ( setter != null )
103             {
104                 try
105                 {
106                     setter.invoke( testngInstance, val );
107                 }
108                 catch ( Exception ex )
109                 {
110                     throw new RuntimeException( "Cannot set option " + key + " with value " + val, ex );
111                 }
112 
113             }
114         }
115     }
116 
117     public static List loadListenerClasses( String listenerClasses )
118         throws TestSetFailedException
119     {
120         if ( listenerClasses == null || "".equals( listenerClasses.trim() ) )
121         {
122             return new ArrayList();
123         }
124 
125         List classes = new ArrayList();
126         String[] classNames = listenerClasses.split( "\\s*,\\s*(\\r?\\n)?\\s*" );
127         for ( int i = 0; i < classNames.length; i++ )
128         {
129             String className = classNames[i];
130             Class clazz = loadClass( className );
131             classes.add( clazz );
132         }
133 
134         return classes;
135     }
136 
137     public static Class loadClass( String className )
138         throws TestSetFailedException
139     {
140         try
141         {
142             return Class.forName( className );
143         }
144         catch ( Exception ex )
145         {
146             throw new TestSetFailedException( "Cannot find listener class " + className, ex );
147         }
148     }
149 
150     /**
151      * Describes a property setter by method name and parameter class
152      *
153      */
154     public static final class Setter
155     {
156         private final String setterName;
157 
158         private final Class paramClass;
159 
160         public Setter( String name, Class clazz )
161         {
162             this.setterName = name;
163             this.paramClass = clazz;
164         }
165 
166         public void invoke( Object target, Object value )
167             throws Exception
168         {
169             Method setter = target.getClass().getMethod( this.setterName, new Class[]{ this.paramClass } );
170             if ( setter != null )
171             {
172                 setter.invoke( target, new Object[]{ convertValue( value ) } );
173             }
174         }
175 
176         Object convertValue( Object value )
177         {
178             if ( value == null )
179             {
180                 return value;
181             }
182             if ( this.paramClass.isAssignableFrom( value.getClass() ) )
183             {
184                 return value;
185             }
186 
187             if ( Boolean.class.equals( this.paramClass ) || boolean.class.equals( this.paramClass ) )
188             {
189                 return Boolean.valueOf( value.toString() );
190             }
191             if ( Integer.class.equals( this.paramClass ) || int.class.equals( this.paramClass ) )
192             {
193                 return new Integer( value.toString() );
194             }
195 
196             return value;
197         }
198     }
199 }